using System;
using TestCases.CompareAssert.Core.Interfaces;

namespace TestCases.CompareAssert.Core
{
    public class CompareContext : ICompareContext
    {
        private readonly IResultBuilderFactory _factory;
        private readonly IComparerObject _left;
        private readonly IComparerObject _right;

        public CompareContext(IResultBuilderFactory factory, IComparerObject left, IComparerObject right)
        {
            _factory = factory;
            _left = left;
            _right = right;
        }

        public IResultBuilderFactory Factory { get { return _factory; } }
        public IComparerObject Left { get { return _left; } }
        public IComparerObject Right { get { return _right; } }
        public object LValue { get { return _left.Object; } }
        public object RValue { get { return _right.Object; } }
        public string LPath { get { return _left.Path; } }
        public string RPath { get { return _right.Path; } }
        public Type LType { get { return _left.Object.GetType(); } }
        public Type RType { get { return _right.Object.GetType(); } }

        public ICompareContext ForIndexedObjects(object left, object right, params object[] indexes)
        {
            return ForObjects(_left.IndexedObject(left, indexes), _right.IndexedObject(right, indexes));
        }

        public ICompareContext ForMethodObjects(object left, object right, string methodName, params object[] parameters)
        {
            return ForObjects(_left.MethodObject(left, methodName, parameters), _right.MethodObject(right, methodName, parameters));
        }

        public ICompareContext ForEntityObjects(object left, object right, string entityName)
        {
            return ForObjects(_left.EntityObject(left, entityName), _right.EntityObject(right, entityName));
        }

        public ICompareContext ForObjects(IComparerObject left, IComparerObject right)
        {
            return (ReferenceEquals(left, _left) && ReferenceEquals(right, _right)) ? this : new CompareContext(_factory, left, right);
        }

        public ICompareContext Reverse()
        {            
            return (ReferenceEquals(_left, _right)) ? this : new CompareContext(_factory, _right, _left);
        }

        public ICompareContext ForFactory(IResultBuilderFactory factory)
        {
            return (ReferenceEquals(factory, _factory)) ? this : new CompareContext(factory, _left, _right);
        }
    }
}